<template>
  <div class="simulation-container">
    <!-- 头部：项目角标 + Navbar 同一行 -->
    <div class="simulation-header-row">
      <div class="project-badge">
        <template v-if="loading">加载中...</template>
        <template v-else-if="error">加载失败：{{ error }}</template>
        <template v-else>
          <span v-if="project?.name">项目：{{ project.name }} </span>
          <span v-else>项目ID: {{ projectId }}</span>
        </template>
      </div>
      <FunctionButton inline />
      <Navbar class="simulation-navbar" />
    </div>
    <!-- 主工作区 -->
    <div class="simulation-body">
      <div v-if="loading" class="loading-mask">正在加载项目...</div>
      <div v-else-if="error" class="error-mask">{{ error }}</div>
      <ResizableTree v-else :projectId="projectId" class="tree-only" />

      <three-scene class="workspace-pane"></three-scene>
    </div>
  </div>
</template>

<script setup lang="ts">
// route：当前路由对象（保持响应式）
// 说明：当 /simulation/:projectId 的参数变化时，组件不会被销毁重建，onMounted 不会再次执行，
// 因此需要使用 onBeforeRouteUpdate（或 watch）来处理后续的参数变化。
import { useRoute, onBeforeRouteUpdate } from 'vue-router'
import { computed, ref, watch } from 'vue'
import {Navbar} from '@/layout/components'
import ResizableTree from '@/views/simulation/resizableTree/index.vue'

import { getProject } from '@/api/system/project'
import ThreeScene from "@/views/simulation/components/ThreeScene.vue";
import FunctionButton from "@/views/simulation/components/FunctionButton.vue";

const route = useRoute()
const rawProjectId = computed(() => route.params.projectId as string | undefined)
// 保持原始字符串 ID，避免超过 2^53 - 1 的数字精度丢失
const projectId = computed(() => rawProjectId.value ?? null)

// 项目数据与状态：
// project   保存后端返回的项目详情；
// loading   请求过程的加载标记；
// error     发生错误时的消息文本（为 null 代表正常）。
const project = ref<any>(null)
const loading = ref(false)
const error = ref<string | null>(null)

let currentAbort: AbortController | null = null
// fetchProject：根据数值化的 projectId 调用后端接口。
// 1. id == null 时直接标记错误并清空数据；
// 2. 请求成功写入 project；失败写入 error；
// 3. finally 中复位 loading。
// 注意：若未来增加“取消上一个请求”功能，可在此处加入 AbortController。
async function fetchProject(id: string | null, retry = 0) {
  if (id == null) { project.value = null; error.value = '缺少项目ID'; return }
  currentAbort?.abort(); currentAbort = new AbortController()
  loading.value = true
  error.value = null
  try {
    const resp = await getProject(id) // 若后端支持 Abort 需传 signal
    project.value = resp?.data || null
    if (project.value) localStorage.setItem('lastProjectId', id)
    if (!project.value && retry < 1) await fetchProject(id, retry + 1)
  } catch (e: any) {
    if (e?.name === 'AbortError') return
    error.value = e?.message || '未知错误'
    project.value = null
  } finally {
    loading.value = false
  }
}

// 初次挂载时主动加载一次。
// 与 onMounted 的区别：这里直接调用即可，不依赖生命周期钩子；如果 component 被 keep-alive 缓存后再次激活而 projectId 没变，不需要重复加载。
fetchProject(projectId.value)

// 监听路由参数变更：当用户从 /simulation/11 切换到 /simulation/12（仍匹配同一个组件）时触发。
// 如果改成 watch 写法：
//   watch(() => route.params.projectId, v => { const id = Number(v); fetchProject(Number.isFinite(id) ? id : null) }, { immediate: true })
// 二选一即可；这里保留 onBeforeRouteUpdate 便于将来做权限校验或阻止导航。
watch(() => route.params.projectId as string | undefined, (raw) => fetchProject(raw ?? null), { immediate: true })
onBeforeRouteUpdate((to) => { fetchProject(to.params.projectId as string ?? null) })
</script>

<style scoped>
.simulation-container {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}
/* 新头部行：左侧项目角标 + 右侧原 Navbar */
.simulation-header-row {
  display: flex;
  align-items: center;
  height: 50px;
  background: var(--navbar-bg, #141414);
  box-shadow: 0 1px 4px rgba(0,21,41,.08);
  padding: 0 12px 0 12px;
  box-sizing: border-box;
  gap: 12px;
}
/* Navbar 占满剩余空间 */
.simulation-navbar { flex: 1; }
/* 隐藏不需要的汉堡与面包屑、顶部菜单 */
.simulation-navbar :deep(.hamburger-container) { display: none; }

/* 项目角标：改为内联块，不再绝对定位 */
.project-badge {
  flex: 0 0 auto;
  background: rgba(0,0,0,0.35);
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 13px;
  letter-spacing: .5px;
  backdrop-filter: blur(2px);
  line-height: 1.2;
  max-width: 320px;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

.simulation-body {
  flex: 1 1 auto;
  position: relative;
  overflow: hidden;
  padding: 0;
  display: flex;
  align-items: stretch;
}
.workspace-pane {
  flex: 1 1 auto;
  min-width: 0;
  position: relative;
  display: flex;
}
/* 强制树组件在此页面只显示左侧树，隐藏其内部 detail 区域 */
.simulation-body :deep(.resizable-tree-wrapper) { width:260px !important; flex:none; }
/* 去掉之前全宽样式可能造成的撑开 */
.simulation-body :deep(.resizable-tree-wrapper) { height:100%; }
/* 移除未使用的旧选择器 (已通过 showDetail 控制) */

/* 新增：加载与错误占位 */
.loading-mask, .error-mask { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:14px; color:#999; z-index:10; background:rgba(0,0,0,.04); }
.error-mask { color: var(--el-color-danger); }
</style>
